package com.spark.sniffer.plugin;

import com.spark.sniffer.logging.api.Logger;
import com.spark.sniffer.logging.api.LoggerFactory;
import com.spark.sniffer.plugin.match.ClassMatch;

import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;


public abstract class AbstractClassEnhancePluginDefine {

    private static final Logger log = LoggerFactory.getLogger(AbstractClassEnhancePluginDefine.class);

    protected AbstractClassEnhancePluginDefine() {
        log.debug("Plugin [{}] loaded.", this.getClass().getName());
    }

    /**
     * Main entrance of enhancing the class.
     *
     * @param typeDescription target class description.
     * @param builder byte-buddy's builder to manipulate target class's bytecode.
     * @param classLoader load the given transformClass
     * @return the new builder, or <code>null</code> if not be enhanced.
     * @throws Exception when set builder failure.
     */
    public DynamicType.Builder<?> define(TypeDescription typeDescription, DynamicType.Builder<?> builder,
        ClassLoader classLoader) throws Exception {
        String transformClassName = typeDescription.getTypeName();
        if (transformClassName == null) {
            return null;
        }
        return this.enhance(typeDescription, builder, classLoader);
    }

    protected abstract DynamicType.Builder<?> enhance(TypeDescription typeDescription,
        DynamicType.Builder<?> newClassBuilder, ClassLoader classLoader) throws Exception;

    /**
     * Define the {@link ClassMatch} for filtering class.
     *
     * @return {@link ClassMatch}
     */
    protected abstract ClassMatch enhanceClass();

    public boolean isBootstrapInstrument() {
        return false;
    }

}
